package com.cicigodd.brick.plug.system.login.service.impl;

import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
import com.cicigodd.brick.plug.common.entity.LoginUser;
import com.cicigodd.brick.plug.common.entity.LoginUserInfo;
import com.cicigodd.brick.plug.common.enums.StatusEnum;
import com.cicigodd.brick.plug.common.enums.UserEnum;
import com.cicigodd.brick.plug.common.exception.BusinessException;
import com.cicigodd.brick.plug.common.utils.HttpServletUtil;
import com.cicigodd.brick.plug.common.utils.PasswordUtil;
import com.cicigodd.brick.plug.jwt.api.JwtServiceContext;
import com.cicigodd.brick.plug.jwt.entity.DefaultJwtPayload;
import com.cicigodd.brick.plug.system.auth.api.AuthServiceContext;
import com.cicigodd.brick.plug.system.auth.api.SessionServiceApi;
import com.cicigodd.brick.plug.system.dict.api.SysDictServiceContext;
import com.cicigodd.brick.plug.system.dict.api.SysDictValueServiceApi;
import com.cicigodd.brick.plug.system.login.request.DyMiniLoginRequest;
import com.cicigodd.brick.plug.system.login.request.LoginRequest;
import com.cicigodd.brick.plug.system.login.request.WxMiniLoginRequest;
import com.cicigodd.brick.plug.system.login.service.LoginService;
import com.cicigodd.brick.plug.system.role.api.SysRoleServiceContext;
import com.cicigodd.brick.plug.weixin.mini.service.WeixinMiniService;
import com.cicigodd.brick.plug.system.login.response.LoginResponse;
import com.cicigodd.brick.plug.system.user.api.SysUserServiceApi;
import com.cicigodd.brick.plug.system.user.entity.SysUser;
import com.cicigodd.brick.plug.system.user.request.SysUserAddRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 系统用户管理
 *
 * @author cicigodd
 * @date 2022/09/22 14:42:03
 */
@Slf4j
@Service
public class LoginServiceImpl implements LoginService {

    /**
     * 用于操作缓存时候加锁
     */
    private static final Object SESSION_OPERATE_LOCK = new Object();

    @Resource
    private SysUserServiceApi sysUserServiceApi;
    @Resource
    private SessionServiceApi sessionServiceApi;
    @Resource
    private WeixinMiniService weixinMiniService;

    @Override
    public LoginResponse login(LoginRequest loginRequest) {
        // 获取用户信息
        LoginUserInfo loginUserInfo = sysUserServiceApi.getUserLoginInfo(loginRequest.getAccount());
        // 校验用户密码是否正确
        Boolean checkResult = PasswordUtil.checkPassword(loginRequest.getPassword(), loginUserInfo.getUserPasswordHexed());
        if (!checkResult) {
            throw new BusinessException("密码错误");
        }
        // 校验用户是否异常
//        if (!StatusEnum.ENABLE.getCode().equals(loginUserInfo.getUserStatus())) {
//            throw new BusinessException("当前用户异常无法登录");
//        }
        // 缓存登录用户
        LoginUser loginUser = loginUserInfo.getLoginUser();
        //生成用户的token
        DefaultJwtPayload defaultJwtPayload = new DefaultJwtPayload(loginUser.getUserId(), loginUser.getAccount(), loginRequest.getRememberMe());

        String jwtToken = JwtServiceContext.me().generateTokenDefaultPayload(defaultJwtPayload);
        loginUser.setToken(jwtToken);
        synchronized (SESSION_OPERATE_LOCK) {
            // 缓存用户信息
            sessionServiceApi.createSession(jwtToken, loginUser);
            sessionServiceApi.removeSessionExcludeToken(jwtToken);
        }
        // 更新用户登录时间和ip
        String ip = HttpServletUtil.getRequestClientIp(HttpServletUtil.getRequest());
        sysUserServiceApi.updateUserLoginInfo(loginUser.getUserId(), loginUser.getLoginTime(), ip);
        return new LoginResponse(loginUser, jwtToken, defaultJwtPayload.getExpirationDate());
    }

    @Override
    public LoginResponse wxlogin(WxMiniLoginRequest wxMiniLoginRequest) throws Exception {

        // 获取微信opneid
        WxMaJscode2SessionResult sessionInfo = weixinMiniService.getSessionInfo(wxMiniLoginRequest.getCode());
        log.info("code换取session：{}", sessionInfo);

        LoginUserInfo loginUserInfo = null;

        SysUser userByAccount = sysUserServiceApi.getUserByAccount(sessionInfo.getOpenid());
        // 用户不存在
        if (ObjectUtil.isNull(userByAccount)) {
            synchronized(this){
                // 新建用户的信息
                SysUserAddRequest sysUserAddRequest = new SysUserAddRequest();
                sysUserAddRequest.setNickName("用户_" + UUID.randomUUID().toString().replaceAll("-",""));
                sysUserAddRequest.setAccount(sessionInfo.getOpenid());
                sysUserAddRequest.setPassword(sessionInfo.getOpenid());
                sysUserAddRequest.setSex("M");
                sysUserAddRequest.setDealerFlag("N");
                sysUserAddRequest.setDealerId(wxMiniLoginRequest.getDealerId());
                sysUserAddRequest.setUserType(UserEnum.MINI.getCode());
                String dictValue = SysDictServiceContext.me().getByTypeAndCode("sys_role_type", "sys_role_type:XCXJS");
                Integer roleId = SysRoleServiceContext.me().getRoleIdByRoleCode(dictValue);
                List<Integer> roleIds = new ArrayList<>();
                roleIds.add(roleId);
                sysUserAddRequest.setRoleIds(roleIds);
                sysUserServiceApi.addUser(sysUserAddRequest);
                // 获取用户信息
                loginUserInfo = sysUserServiceApi.getUserLoginInfo(sessionInfo.getOpenid());
            }
        }else{
            // 获取用户信息
            loginUserInfo = sysUserServiceApi.getUserLoginInfo(sessionInfo.getOpenid());
        }

        // 校验用户是否异常
//        if (!StatusEnum.ENABLE.getCode().equals(loginUserInfo.getUserStatus())) {
//            throw new BusinessException("当前用户异常无法登录");
//        }
        // 缓存登录用户
        LoginUser loginUser = loginUserInfo.getLoginUser();
        //生成用户的token
        DefaultJwtPayload defaultJwtPayload = new DefaultJwtPayload(loginUser.getUserId(), loginUser.getAccount(), false);

        String jwtToken = JwtServiceContext.me().generateTokenDefaultPayload(defaultJwtPayload);
        loginUser.setToken(jwtToken);
        synchronized (SESSION_OPERATE_LOCK) {
            // 缓存用户信息
            sessionServiceApi.createSession(jwtToken, loginUser);
            sessionServiceApi.removeSessionExcludeToken(jwtToken);
        }
        // 更新用户登录时间和ip
        String ip = HttpServletUtil.getRequestClientIp(HttpServletUtil.getRequest());
        sysUserServiceApi.updateUserLoginInfo(loginUser.getUserId(), loginUser.getLoginTime(), ip);
        return new LoginResponse(loginUser, jwtToken, defaultJwtPayload.getExpirationDate());
    }

    @Override
    public void logout() {
        String token = AuthServiceContext.me().getToken();
        sessionServiceApi.removeSession(token);
    }
}
